package org.example.movie;

import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.*;
import org.example.RtspInfo;

import static org.bytedeco.opencv.global.opencv_core.absdiff;
import static org.bytedeco.opencv.global.opencv_core.mean;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

/**
 * @author zehua
 * @date 2023/11/8 9:59
 * @Description TODO  对比两个视频流的画面差异
 * TODO 对比分为两个方向
 * 1.主动播放的视频和回播展示的画面是否一致
 * 2.主会场和分会场的视频流是否差异过大（网络抖动相关 给予一个合理的范围）
 * @since V1.1.0
 */
public class CompareVideoStreams {


    public static void main(String[] args) {
        String sourceUrl = RtspInfo.RTSP_URL_CAMERA;
        String playbackUrl = RtspInfo.RTSP_URL_CAMERA;


        OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
        OpenCVFrameConverter.ToMat converterPlay = new OpenCVFrameConverter.ToMat();
        FFmpegFrameGrabber sourceGrabber = new FFmpegFrameGrabber(sourceUrl);
        FFmpegFrameGrabber playbackGrabber = new FFmpegFrameGrabber(playbackUrl);
        try {
            sourceGrabber.start();
            playbackGrabber.start();
            Frame sourceFrame; // 理解为分会场视频流
            Frame playbackFrame;// 理解为主会场的播放分会场的视频流
            int i = 0;
            while ((sourceFrame = sourceGrabber.grabImage()) != null &&
                    (playbackFrame = playbackGrabber.grabImage()) != null) {
                Mat sourceMat = converter.convert(sourceFrame);
                Mat playbackMat = converterPlay.convert(playbackFrame);
                //转换为灰度进行比较
                Mat sourceGray = new Mat();
                Mat playbackGray = new Mat();
//                    if (sourceGray == null || playbackGray == null){
//                        System.out.println("视频原播放流 和  对比流画面不存在");
//                    }

                if (sourceMat != null && i % 30 == 0) {
                    try {
                        cvtColor(sourceMat, sourceGray, COLOR_BGR2GRAY);
                        cvtColor(playbackMat, playbackGray, COLOR_BGR2GRAY);
                        // 计算帧之间的差异
                        Mat diff = new Mat();
                        absdiff(sourceGray, playbackGray, diff);
                        //评估差异，例如使用平均值
                        Scalar diffMean = mean(diff);
                        // 相同视频的different 为0  值越大 画面差异越大
                        System.out.println("Difference: " + diffMean.get(0));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                i++;
            }
            System.out.println("视频原播放流 和  对比流不存在");
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        } finally {
            // **注意一定要关闭   不然下次启动视频流无法打开
            try {
                converter.close();
                converterPlay.close();

                sourceGrabber.close();
                playbackGrabber.close();
            } catch (FFmpegFrameGrabber.Exception e) {
                e.printStackTrace();
            } catch (FrameGrabber.Exception e) {
                e.printStackTrace();
            }
        }
    }
}
